package com.gitee.sparta.core.process;

import com.gitee.sparta.annotation.BroadcastListener;
import com.gitee.sparta.annotation.FinalRetry;
import com.gitee.sparta.annotation.SpartaListener;
import com.gitee.sparta.core.process.feature.SpartaTaskDispatcherFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * sparta 启动阶段，需要扫描 @SpartaListener 注解所在的类，
 * 并进行存储方便后续的使用
 *
 * @author zyred
 * @since v 0.0.1
 */
@SuppressWarnings("all")
@Slf4j
public class SpartaAnnotationBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> beanClazz = bean.getClass();
        Method[] declaredMethods = beanClazz.getDeclaredMethods();
        for (Method method : declaredMethods) {

            if (method.isAnnotationPresent(SpartaListener.class)) {
                SpartaListener spartaListener = method.getAnnotation(SpartaListener.class);
                this.processAnnotation(spartaListener.topics(), beanName, method, bean, SpartaListener.class);
            }

            if (method.isAnnotationPresent(FinalRetry.class)) {
                FinalRetry finalRetry = method.getAnnotation(FinalRetry.class);
                this.processAnnotation(finalRetry.topics(), beanName, method, bean, FinalRetry.class);
            }

            // 新增 广播 的监听器注解扫描
            if (method.isAnnotationPresent(BroadcastListener.class)) {
                BroadcastListener broadcastListener = method.getAnnotation(BroadcastListener.class);
                this.processAnnotation(broadcastListener.channels(), beanName, method, bean, BroadcastListener.class);
            }
        }
        return bean;
    }


    private void processAnnotation ( String[] topics, String beanName, Method method, Object bean, Class<?> clazz) {
        if (log.isDebugEnabled()) {
            log.debug("[Sparta ] Post processor bean [{}] contains {}, topics : {}",
                    beanName, clazz.getSimpleName(), Arrays.asList(topics));
        }

        SpartaTaskDispatcherFeature.registerSpartaBeanMapping(topics, bean, method, clazz, beanName);
    }
}
